package cmd

import (
	"flag"
	"fmt"
	"github.com/pkg/errors"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/uber/jaeger-lib/metrics"
	jexpvar "github.com/uber/jaeger-lib/metrics/expvar"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"

	"bilinadmin/internal"
	"bilinadmin/internal/conf"
	"bilinadmin/pkg/log"
	"bilinadmin/pkg/middleware"
)

var (
	zapLogger      *zap.Logger
	configFile     string
	metricsFactory metrics.Factory
)

func init() {
	// 日志初始化
	initLogger()
	// 系统监控
	metricsFactory = jexpvar.NewFactory(10)
	// 配置文件加载
	flag.StringVar(&configFile, "c", "./config.toml", "path of mall config file.")
	flag.Parse()
}

// initLogger logger initialize
func initLogger() {
	c := zap.NewProductionEncoderConfig()
	c.EncodeTime = zapcore.ISO8601TimeEncoder
	c.TimeKey = "time"
	core := zapcore.NewCore(
		zapcore.NewJSONEncoder(c),
		zapcore.AddSync(os.Stdout),
		zap.NewAtomicLevelAt(zap.InfoLevel))
	zapLogger = zap.New(core, zap.AddStacktrace(zapcore.FatalLevel), zap.AddCaller())
}

// InitBilinAdmin 启动 admin
func InitBilinAdmin() error {
	// logger
	logger := log.NewFactory(zapLogger)
	logger.With(zap.String("service", "bilinadmin"))
	logger.Bg().Info(fmt.Sprintf("config file %s", configFile))
	cfg, err := conf.Init(configFile)
	if err != nil {
		logger.Bg().Panic(fmt.Sprintf("配置文件初始化失败: %s", err.Error()))
		return err
	}
	if cfg == nil {
		logger.Bg().Panic("配置文件初始化失败: 配置为空")
		return errors.New("配置文件为空")
	}
	runtime.GOMAXPROCS(cfg.Base.MaxProc)
	// 链路追踪
	_, tracingClose := middleware.TracingInit("bilinadmin", metricsFactory, logger)
	defer func() {
		_ = tracingClose.Close()
	}()

	server := internal.NewServer(logger, cfg)
	server.Run()

	// signal
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
	s := <-c
	logger.Bg().Info("report get a signal", zap.String("signal", s.String()))
	switch s {
	case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
		server.Close()
		return nil
	case syscall.SIGHUP:
	default:
		return nil
	}
	return nil
}
